#include "logout.hh"
#include <iostream>
#include <memory>
#include <string>
#include <strings.h>
#include <cstring>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
using namespace std;

#define buffer_size 1024

class tcp_server_t
{
public:
    tcp_server_t(string addr, uint16_t port)
    {
        // tcp
        _listen_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_socket_fd < 0)
        {
            log_error("creat_listen_socket_error!", SOCKET_CREAT_ERROR);
        }
        // info
        sockaddr_in host_addr;
        bzero(&host_addr, sizeof(host_addr));
        host_addr.sin_addr.s_addr = (addr.empty() ? INADDR_ANY : inet_addr(addr.c_str()));
        host_addr.sin_family = AF_INET;
        host_addr.sin_port = htons(port);
        // bind
        if (bind(_listen_socket_fd, (const sockaddr *)&host_addr, sizeof(host_addr)) < 0)
        {
            log_error("bind_error!", BIND_ERROR);
        }
        int opt=1;
        setsockopt(_listen_socket_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
        setsockopt(_listen_socket_fd,SOL_SOCKET,SO_REUSEPORT,&opt,sizeof(opt));
    }
    void run()
    {
        //监听
        if (listen(_listen_socket_fd, 5) < 0)
        {
            log_error("listen_error!", LISTEN_ERROR);
        }
        sockaddr_in client;
        socklen_t client_len = sizeof(client);

        while (true)
        {
            //连接
            int client_fd = accept(_listen_socket_fd, (sockaddr *)&client, &client_len);
            if (client_fd < 0)
            {
                log_error("accept_error!", ACCEPT_ERROR);
            }
            //新建执行流(子进程,或多线程)提供服务
            //线程
            pthread_t tid = 0;
            client_thread_argc *argc = new client_thread_argc{client_fd, this};
            if (pthread_create(&tid, 0, thread_routine, argc) < 0)
            {
                log_error("thread_create_error!", THREAD_CREATE_ERROR);
            }
        }
    }

private:
    static void *thread_routine(void *argc_struct)
    {
        //分离
        pthread_detach(pthread_self());
        //简易远程shell服务
        auto argc = (client_thread_argc *)argc_struct;
        char read_buffer[buffer_size];
        char send_buffer[buffer_size];
        while (true)
        {
            bzero(read_buffer, buffer_size);
            bzero(send_buffer, buffer_size);
            //接收
            ssize_t read_size = read(argc->_fd, read_buffer, buffer_size);
            if (read_size == 0 || strcasecmp(read_buffer, "exit") == 0)
                break;
            if (strncasecmp(read_buffer, "rm", 2) == 0 || strncasecmp(read_buffer, "unlink", 6) == 0){
                cout<<"rm || unlink"<<endl;
                const char* tmp ="Permission denied\n";
                write(argc->_fd, tmp,strlen(tmp));
                continue;
            }
            // popen
            FILE *res_file = popen(read_buffer, "r");
            if (res_file <= 0)
            {
                log_error("popen_error", POPEN_ERROR);
            }
            //执行指令,读取结果并转发给用户
            while (fgets(send_buffer,buffer_size,res_file)!=nullptr)
            {
                cout<<send_buffer;
                //带'\n'
                write(argc->_fd, send_buffer,strlen(send_buffer));
            }
            //没有输出的指令也提供反馈
            write(argc->_fd, "",1);
        }
        cout<<"exit..."<<endl;
        //切记资源泄漏
        close(argc->_fd);
        delete argc;
    }

private:
    struct client_thread_argc
    {
        client_thread_argc(int fd, tcp_server_t *pthis)
            : _fd(fd), _this(pthis) { ; }
        tcp_server_t *_this;
        int _fd;
    };
    int _listen_socket_fd;
};